import React from 'react'
import NavHeader from 'common/NavHeader'
import styles from './index.module.scss'
import { getCurrentCity } from 'utils/city'
import http from 'utils/http'
import { Toast } from 'antd-mobile'
import classNames from 'classnames'
import HouseItem from 'common/HouseItem'

// 通过 styles对象, 是可以拿到改动后的类名的, 将来设置给盒子即可

const BMap = window.BMap

class Map extends React.Component {
  state = {
    isShow: false,
    houseList: [],
  }
  async componentDidMount() {
    // 获取当前定位的或者用户选择的城市
    const city = await getCurrentCity()
    console.log(city)

    // 创建地图实例
    this.map = new BMap.Map('container')
    // 根据城市要展示地图了
    // 需求: 需要根据城市名字, 先转换成经纬度, 在完成地图的展示
    // 1. 创建地址解析器
    const myGeo = new BMap.Geocoder()
    // 2. 解析, 得到坐标点
    //    参数1: 具体的地址(中文地址)
    //    参数2: 回调函数, 可以拿到定位的经纬度坐标point
    //    参数3: 市级的名称
    myGeo.getPoint(
      city.label,
      async (point) => {
        // 根据得到的坐标, 作为中心点展示
        this.map.centerAndZoom(point, 11)
        // 添加控件
        this.map.addControl(new BMap.NavigationControl()) // + - 号, 放大缩小地图
        this.map.addControl(new BMap.ScaleControl()) // 显示比例尺

        // 给地图注册开始滑动的事件 (地图开始移动)
        this.map.addEventListener('movestart', () => {
          this.setState({
            isShow: false,
          })
        })

        // 根据city.value, 发送请求, 渲染区的覆盖物
        this.renderOverlays(city.value)
      },
      city.label
    )
  }
  // 发送请求, 添加覆盖物
  async renderOverlays(id) {
    Toast.loading('加载中...', 0)

    // 1. 发送请求
    const res = await http.get(`/area/map?id=${id}`)

    // 2. 获取列表
    const list = res.data.body
    const { type, nextZoom } = this.getTypeAndZoom()
    // 3. 遍历列表, 添加覆盖物
    list.forEach((item) => {
      // 添加覆盖物, 需要类型, 需要级别
      this.addOverlay(item, type, nextZoom)
    })

    Toast.hide()
  }

  // 根据当前的缩放级别, 得到下一级的缩放级别和要渲染的覆盖物的类型
  getTypeAndZoom() {
    const zoom = this.map.getZoom()
    let type, nextZoom
    if (zoom === 11) {
      // 渲染区的数据(浦东新区)
      type = 'circle'
      nextZoom = 13
    } else if (zoom === 13) {
      // 渲染镇的数据(航头镇)
      type = 'circle'
      nextZoom = 15
    } else {
      // 渲染小区的数据(海州桃花园)
      type = 'rect'
      nextZoom = 15
    }
    return {
      type,
      nextZoom,
    }
  }

  // 封装一个方法, 专门添加覆盖物
  // 添加覆盖物, 需要知道添加的是圆形的还是方形的
  addOverlay(item, type, nextZoom) {
    if (type === 'circle') {
      this.addCircle(item, nextZoom)
    } else {
      this.addRect(item, nextZoom)
    }
  }

  addCircle(item, nextZoom) {
    console.log('渲染圆形覆盖物', item, nextZoom)
    // 1. 创建坐标点
    const point = new BMap.Point(item.coord.longitude, item.coord.latitude)
    // 2. 创建覆盖物对象
    const label = new BMap.Label(
      `<div class="bubble">
        <p class="name">${item.label}</p>
        <p>${item.count}套</p>
      </div>`,
      {
        position: point, // 指定文本标注所在的地理位置
        offset: new BMap.Size(-35, -35), //设置文本偏移量
      }
    )
    // 3. 给覆盖物重置样式
    label.setStyle({
      border: 'none',
      padding: 0,
    })
    // 4. 往地图上添加覆盖物
    this.map.addOverlay(label)

    // 5. 给覆盖物-添加点击事件
    label.addEventListener('click', () => {
      // (1) 放大地图, 居中
      this.map.centerAndZoom(point, nextZoom)
      // (2) 清除原有的覆盖物
      setTimeout(() => {
        this.map.clearOverlays()
      }, 0)

      // (3) 根据id, 加载下一级数据, 并渲染覆盖物
      this.renderOverlays(item.value)
    })
  }

  addRect(item, nextZoom) {
    console.log('渲染方形覆盖物', item, nextZoom)
    // 1. 创建坐标点
    const point = new BMap.Point(item.coord.longitude, item.coord.latitude)
    // 2. 创建覆盖物对象
    const label = new BMap.Label(
      `<div class="rect">
          <span class="housename">${item.label}</span>
          <span class="housenum">${item.count} 套</span>
          <i class="arrow"></i>
       </div>`,
      {
        position: point, // 指定文本标注所在的地理位置
        offset: new BMap.Size(-50, -22), //设置文本偏移量
      }
    )
    // 3. 给覆盖物重置样式
    label.setStyle({
      border: 'none',
      padding: 0,
    })
    // 4. 往地图上添加覆盖物
    this.map.addOverlay(label)

    // 5. 给覆盖物, 添加点击事件
    // panTo(point) 以点为中心, 慢慢地让地图居中 (以点为中心, 展示地图)
    // panBy(x, y)  位移x, y的距离 (好处: 可以移动到地图上你想要的位置)
    label.addEventListener('click', (e) => {
      Toast.loading('加载中...', 0)

      // (1) 让小区, 在可见的地图区域, 中心展示
      const centerX = window.innerWidth / 2
      const centerY = 45 + (window.innerHeight - 330 - 45) / 2
      const x = centerX - e.changedTouches[0].pageX
      const y = centerY - e.changedTouches[0].pageY
      this.map.panBy(x, y)

      // (2) 发送ajax请求, 数据回来了, 显示列表数据
      http.get(`/houses?cityId=${item.value}`).then((res) => {
        const houseList = res.data.body.list
        this.setState({
          houseList,
          isShow: true,
        })

        Toast.hide()
      })
    })
  }

  render() {
    // 类名设置 className={`houseList ${this.state.isShow ? 'show' : ''}`}
    // 类名设置 className={'houseList ' + (this.state.isShow ? 'show' : '')}

    return (
      <div className={styles.map}>
        <NavHeader>地图找房</NavHeader>

        <div id="container" className="container"></div>

        {/* 房源列表 */}
        <div className={classNames('houseList', { show: this.state.isShow })}>
          <div className="titleWrap">
            <h1 className="listTitle">房屋列表</h1>
            <a className="titleMore" href="/house/list">
              更多房源
            </a>
          </div>
          <div className="houseItems">
            {this.state.houseList.map((item) => (
              <HouseItem key={item.houseCode} item={item}></HouseItem>
            ))}
          </div>
        </div>
      </div>
    )
  }
}

export default Map
